/*
* VFilter.h: 2008-3-31**
* Define a virtual class Filter to do optimization on VBlock, Many
* filters can be implemented to do appropriate optimizations. **
* xxxFilter can do xxx on VBlock**
* By: CrossBit Group, vivy**
*
* Last Modified:
*     Gxf, 2008-12-12. 
*     Add some new interfaces for vfilter which enables VFilter to
*     handle all filters and do object counting.
*
*/

#ifndef VFILTER_H
#define VFILTER_H

#include <vector>
#include <algorithm>
#include "crossbit/common.h"
#include "crossbit/VBlock.h"


namespace crossbit{

    class VFilter{
        public:
            // The type of operations to apply filter

            enum VF_TYPE{ 
                INT_BASIC_BLOCK = 0,
                INT_SUPER_BLOCK,
                FLOAT_BASIC_BLOCK,
                FLOAT_SUPER_BLOCK,
                MAX_TYPE,
                BEGIN_TYPE = INT_BASIC_BLOCK,
            };

        public:
            VFilter(){ 
                // Object counting
                _cnt++; 
            }
            virtual ~VFilter(){
                if (--_cnt == 0){
                    int tp;
                    for(tp = BEGIN_TYPE; tp < MAX_TYPE; tp++){
                        delete _filters[tp];
                    }
                }
            }
            
            virtual XTUint32 run(VBlock *vb) = 0;

        public:
            typedef std::vector<VFilter *>::iterator iterator;

            inline static void registerFilter(VFilter * filter, VF_TYPE filter_type){
                if (_filters[filter_type] == NULL)
                    _filters[filter_type] = new std::vector<VFilter *>;
                _filters[filter_type] -> push_back(filter);
            }

            inline static void unRegisterFilter(VFilter * filter, VF_TYPE filter_type){
                _filters[filter_type] -> 
                    erase(remove(_filters[filter_type] -> begin(), 
                                 _filters[filter_type] -> end(), 
                                 filter), 
                         _filters[filter_type] -> end());
            }

            inline static void clearFilters(){
                int tp = BEGIN_TYPE;
                while(tp < MAX_TYPE){
                    _filters[tp] -> clear();
                    tp++;
                }
            }

            inline static void runFilters(VBlock * vb){
                int tp;
                for(tp = BEGIN_TYPE; tp < MAX_TYPE; tp++){
                    if ((tp == INT_BASIC_BLOCK || tp == INT_SUPER_BLOCK) && 
                         AllIntOp(vb) == false){
                        // If there is any floating point inst, 
                        // don't do the optimization 
                        continue;
                    }
                    else if (_filters[tp] == NULL){
                        continue;
                    }
                    else{
                        iterator itr = _filters[tp] -> begin();
                        while(itr != _filters[tp] -> end()){
                            (*itr) -> run(vb);
                            itr++;
                        }
                    }
                }
            }

        protected:
            // Check if there is any float operations
            inline static bool AllIntOp(VBlock *vb){
                VBlock::vb_iterator Itr = vb->begin(); 
                VBlock::vb_iterator End = vb->end();

                for(; Itr != End; Itr++) { 
                    if(true == IsFloatOp((*Itr) -> getOpcode())){ 
                        return false; 
                    } 
                } 
                return true;
            }



        protected:
            static std::vector<VFilter *> * _filters[MAX_TYPE];
            static XTInt32                  _cnt;

    };
    
    //=============================================================
    //Definition of various VFilters
    //=============================================================
    
    //PrintFilter: print vinsts in VBlock
    class PrintFilter : public VFilter{
        
        public: 
            XTUint32 run(VBlock *);
    };
    
    // DumpFilter
    class DumpFilter : public VFilter{
        
        public: 
            XTUint32 run(VBlock *);
    };

    //SSAFormFilter: SSA form for VBlock
    class SSAFormFilter : public VFilter{
      
        public: 
            XTUint32 run(VBlock *);
    };
    
    //RedundancyEliminateFilter: Eliminate redundancy for VBlock
    class RedundancyEliminateFilter : public VFilter{
     
         public: 
            XTUint32 run(VBlock *);
    };

    class V0Filter: public VFilter{
     
         public: 
            XTUint32 run(VBlock *);
    };

    class CopyPropagationFilter: public VFilter{
     
         public: 
            XTUint32 run(VBlock *);
    };


    //CollectNextUseInfoFilter: collect V_registers next use information for register allocation 
    class CollectNextUseInfoFilter : public VFilter{
      
          public: 
             XTUint32 run(VBlock *);
              
          private: 
              const static XTInt32 UNMAPPED = 0x01;
              const static XTInt32 MAPPED = 0x02;
              const static XTInt32 SPILLED = 0x04;
           
              struct RegUsage{
                  XTInt32 status;
                  XTRegNum map;
                  XTInt32 inst;
              };
    };
    
}

#endif

